package com.stxx.stiot2.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.stxx.framwork.domain.model.Option;
import com.stxx.framwork.domain.model.PageQuery;
import com.stxx.framwork.domain.model.PageResult;
import com.stxx.framwork.tran.TranUtils;
import com.stxx.framwork.utils.StoreUtils;
import com.stxx.stiot2.constants.RedisKeys;
import com.stxx.stiot2.constants.SystemConstants;
import com.stxx.stiot2.domain.Gateway;
import com.stxx.stiot2.domain.cache.GatewayCache;
import com.stxx.stiot2.external.RedisServer;
import com.stxx.stiot2.service.GatewayService;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.sql.SqlBuilder;

import java.sql.SQLException;
import java.util.List;

/**
 * @author Fuzhenlei
 * @date 2025/01/15 16:41
 */
@Component
public class GatewayServiceImpl implements GatewayService {

    @Inject
    StoreUtils storeUtils;
    @Inject
    RedisServer redisServer;

    public String getKey(String id){
        return RedisKeys.gateway_info+id;
    }
    @Override
    public GatewayCache getCache(String id){
        String key = getKey(id);
        GatewayCache gatewayCache = redisServer.getObj(key,GatewayCache.class);
        if(gatewayCache!=null){
            return gatewayCache;
        }
        Gateway gateway = this.queryById(id);
        if(gateway==null){
            return null;
        }
        GatewayCache cache = BeanUtil.toBean(gateway,GatewayCache.class);
        redisServer.setObj(key,cache);
        return cache;
    }


    @Override
    public Gateway queryById(String id) {
        try {
            return storeUtils.selectById(id,Gateway.class);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    @Override
    public int insert(Gateway bean) throws SQLException {
        validEntityBeforeSave(bean);
        return storeUtils.insert(bean);
    }

    @Override
    public int update(Gateway bean) throws SQLException {
        validEntityBeforeSave(bean);
        int i = storeUtils.update(bean);
        if(i>0){
            redisServer.setObj(getKey(bean.getCode()),BeanUtil.toBean(bean,GatewayCache.class));
        }
        return i;
    }
    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Gateway bean){

    }
    @Override
    public int delete(String name) throws SQLException {
        redisServer.delete(getKey(name));
        return storeUtils.delete(Gateway.class, name);
    }

    @Override
    public int deleteByIds(String[] ids) throws SQLException {
        String[] keys = new String[ids.length];
        for(int i =0;i<ids.length;i++){
            keys[i] = getKey(ids[i]);
        }
        redisServer.delete(keys);
        return storeUtils.deleteByIds(Gateway.class,ids);
    }

    @Override
    public List<Gateway> list(Gateway obj) throws SQLException {
        offline();
        List<Gateway> list = storeUtils.selectList(Gateway.class,obj);
        return list;
    }

    @Override
    public PageResult<Gateway> pageList(Gateway obj, PageQuery pageQuery) throws SQLException {
        offline();
        PageResult<Gateway> pageResult = storeUtils.selectPageList(Gateway.class,obj,pageQuery);
        TranUtils.build().add("driverType").tran(pageResult.getData());
        return pageResult;
    }
    private static Long lastRefreshTime = 0L;
    void offline() throws SQLException {
        if(System.currentTimeMillis() - lastRefreshTime < 30000){
            return;
        }
        lastRefreshTime = System.currentTimeMillis();
        SqlBuilder sb = new SqlBuilder();
        sb.append("update "+storeUtils.getTableName("gateway")+" set online=0 where timeout_enable=1");
        sb.append(" and last_report_time+timeout_second*1000 < ?",System.currentTimeMillis());
        sb.append(" and online=1");
        storeUtils.sql(sb).update();
    }

    @Override
    public List<Option> queryOptions(String id, String w,String pid) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select code as value,name as label from "+storeUtils.getTableName("gateway"));
        if(id != null){
            sb.append(" where code=?",id);
        }else{
            sb.append(" where (code like concat('%',?,'%') or name like concat('%',?,'%'))",w,w);
        }
        sb.append(" limit "+ SystemConstants.options_query_max_size);
        return storeUtils.sql(sb).queryRowList(Option.class);
    }

    @Override
    public List<Option> queryOptions(String[] ids) throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select code as value,name as label from "+storeUtils.getTableName("gateway")+" where code in (");
        sb.append(StrUtil.repeat("?,",ids.length));
        sb.removeLast();
        sb.append(")",ids);
        return storeUtils.sql(sb).queryRowList(Option.class);
    }

    @Override
    public List<Gateway> listActive() throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select * from "+storeUtils.getTableName("gateway")+" where active = 1");
        return storeUtils.sql(sb).queryRowList(Gateway.class);
    }

    @Override
    public List<Gateway> listMqtt() throws SQLException {
        SqlBuilder sb = new SqlBuilder();
        sb.append("select * from "+storeUtils.getTableName("gateway")+" where active = 1 and driver_type = 'MQTT'");
        return storeUtils.sql(sb).queryRowList(Gateway.class);
    }

    @Override
    public int updateLastReportTime(GatewayCache gatewayCache) throws SQLException {
        redisServer.setObj(getKey(gatewayCache.getCode()),gatewayCache);
        SqlBuilder sb = new SqlBuilder();
        sb.append("update ")
                .append(StoreUtils.getTableName("gateway")).append(" set last_report_time=?,online=1 where code = ?",gatewayCache.getLastReportTime(),gatewayCache.getCode());
        return storeUtils.sql(sb).update();
    }


//    @Override
//    public GatewayState getGatewayState(String gatewayCode){
//        return redisServer.getObj(RedisKeys.gateway+gatewayCode,GatewayState.class);
//    }
//
//    @Override
//    public void getGatewayState(String gatewayCode, GatewayState state){
//        redisServer.setObj(RedisKeys.gateway+gatewayCode,state);
//    }
}
